import os
import sys
import subprocess
from uuid import uuid4
from distutils.core import setup, Command, DistutilsOptionError
from distutils.command.install import install as _install
from distutils.file_util import move_file
from distutils.dir_util import mkpath
from shutil import copyfile

# The python packages that this setup is going to install
package_list = [
'mediadart',
'libxmp',
'mediadart.servers',
'mediadart.config',
'mediadart.mqueue',
'mediadart.storage',
'mediadart.log',
'mediadart.rest',
'mediadart.lock',
'mediadart.uploader',
]

# Names of required debian packages. Each entry specifies:
# <package_name>  <list of args of apt-get install (version numbers etc.)>
debian_packages = [
'python-twisted',
'python-twisted-web',
'python-amqplib',
'rabbitmq-server',
'ffmpeg',
'ffprobe',
'imagemagick',
'gstreamer0.10-plugins-base',
'gstreamer0.10-plugins-good',
'gstreamer0.10-plugins-bad',
'gstreamer0.10-plugins-bad-multiverse',
'gstreamer0.10-plugins-ugly',
'gstreamer0.10-plugins-ugly-multiverse',
'gstreamer0.10-ffmpeg',
'libsdl-image1.2',
'python-gst0.10',
'libexempi3',
'soundstretch',
]

# list of <tarfile>, <unpacked directory, None if unpacks in curdir>, <install_command>
tarfiles = [
('python-txamqp-trunk.tgz', 'txamqp', ['python', 'setup.py', 'install']),
]


#
# Utility functions
#
def _run(cmdline, as_root, failures):
    if as_root:
        cmdline.insert(0, 'sudo')
    ret = subprocess.call(cmdline)
    if ret > 0:
        failures.append('Error executing %s' % ' '.join(cmdline))
    return ret

def _install_tar(failures):
    "install the tarballs"
    curdir = os.getcwd()
    for tarfile, topdir, exe in tarfiles:
        print ('\n######## Installing %s' % tarfile)
        clean_up = topdir and not os.path.exists(topdir)  # delete new directories
        _run(['tar', 'xvzf', tarfile], 1, failures)
        if topdir and os.path.exists(topdir):
            os.chdir(topdir)
            _run(exe, 1, failures)
        os.chdir(curdir)
        if clean_up:
            print 'Removing %s' % topdir
            _run(['rm', '-rf', topdir], 1, failures)


def _install_debian(failures):
    "install the debian packages"
    response = raw_input('\nDependencies:%s%s\nInstall? (y/N): ' % (
          '\n - '.join([''] + debian_packages), '\n - '.join([''] + [x[0] for x in tarfiles])))
    if not response or response.lower().startswith('n'):
        print('Aborting installation of dependencies')
        return
    for pkg in debian_packages:
        print ('\n Installing %s' % pkg)
        _run(['apt-get', 'install', pkg], 1, failures)
    _install_tar(failures)

def _adapt_cfg(cfgroot, as_root, source_cfg, target_cfg, failures):
    """rewrite in the given cfg file the full path of all executables.
    
    target_cfg must be writable
    """
    if not os.path.exists(cfgroot):
        _run(['mkdir', '-p', cfgroot], as_root, failures)
        _run(['chmod', '755', cfgroot], as_root, failures)
    tmpfilename = os.path.join(os.sep, 'tmp', uuid4().get_hex())
    tmpfile = open(tmpfilename, 'w')
    with open(source_cfg, 'r') as f:
        for line in f:
            parsed = [x.strip() for x in line.split('=')]
            if len(parsed) == 2 and not parsed[0].startswith('#') and parsed[0].endswith('_exe'):
                cmd = subprocess.Popen(['which', parsed[1]], stdout=subprocess.PIPE, stderr=f)
                if cmd.wait() > 0:
                    failures.append('##### WARNING: executable %s not found' % parsed[1])
                    fullpath=parsed[1]
                else:
                    fullpath = cmd.stdout.readlines()[0].strip()
                tmpfile.write('%s=%s\n' % (parsed[0], fullpath))
            else:
                tmpfile.write(line)
    tmpfile.close()
    _run(['mv', '-f', tmpfilename, target_cfg], as_root, failures)

def _rename_launcher(basedir, failures):
    "Change the name of the laucher to mediadart"
    launcher = os.path.join(basedir, 'mediadart')
    _run(['mv', '-f', os.path.join(basedir, 'launch.py'), launcher], 1, failures)

def _install_scripts(destination, scripts, failures):
    for script in scripts:
        filename = os.path.basename(os.path.normpath(script))
        target = os.path.join(destination, filename)
        ret = _run(['cp', '-f', script, target], 1, failures)
        if ret == 0:
            _run(['chmod', '555', target], 1, failures)


def _print_errors(failures):
    if failures:
        print >>sys.stderr, '\n### Errors during installation:'
        print >>sys.stderr, '\n'.join(failures)

#
# Custom commands
#
class install(_install):
    def run(self):
        failures = []
        _install_debian(failures)
        _install.run(self)
        _rename_launcher(self.install_scripts, failures)
        cfgroot = os.path.join(os.sep, 'etc', 'mediadart')
        _adapt_cfg(cfgroot, 1,
                  os.path.join('mediadart', 'config', 'mediadart.cfg'),
                  os.path.join( cfgroot, 'mediadart.cfg'), failures)
        _print_errors(failures)

class local_install(_install):
    description = "install leaving the source tree in-place: need to set PYTHONPATH"

    def run(self):
        failures = []
        _install_debian(failures)
        _install_scripts(self.install_scripts, self.distribution.scripts or [], failures)
        _run(['python', 'setup.py', 'install_data'], 1, failures)
        if 'HOME' in os.environ:
            cfgroot = os.path.join(os.environ['HOME'], '.mediadart')
            as_root = 0
        else:
            cfgroot = os.path.join(os.sep, 'etc', 'mediadart')
            as_root = 1
        _adapt_cfg(cfgroot, as_root,
                  os.path.join('mediadart', 'config', 'mediadart.cfg'),
                  os.path.join(cfgroot, 'mediadart.cfg'), failures)
        _print_errors(failures)

setup(name='mediadart', 
      version='1.0.16', 
      description='Mediadart media framework',
      long_description='A framework for the distributed processing of media resources based on AMQP and RabbitMQ for messaging',
      author='CRS4',
      author_email='orlando@crs4.it',
      license='LGPL',
      platforms=['Unix'],
      url='http://code.google.com/p/mediadart', 
      packages= package_list,
      scripts=['mediadart/adapter/gst-discover', 'mediadart/launch.py'],
      package_data = {'mediadart': ['mqueue/amqp0-8.xml']},
      data_files = [('/usr/local/lib/gstreamer-0.10', ['watermarkplugin/src/.libs/libgstmediadart.so'])],
      cmdclass={'install': install, 'local_install': local_install },
     )

